package fun.ticsmyc.rpc.client;

import fun.ticsmyc.rpc.Config;
import fun.ticsmyc.rpc.client.annotation.RpcClient;
import fun.ticsmyc.rpc.client.proxy.ServiceProxy;
import fun.ticsmyc.rpc.common.util.AopTargetUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;

/**
 * @author Ticsmyc
 * @date 2020-11-18 21:52
 */
@Component
public class ServiceProxyCreaterBeanPostProcessor implements BeanPostProcessor {

    private static final Logger logger = LoggerFactory.getLogger(ServiceProxyCreaterBeanPostProcessor.class);

    /**
     * 调用时机 ： bean的初始化结束后，被使用之前
     * 在这里检查这个bean的所有field， 看是否有标注@RpcClient
     * 如果标注了@RpcClient，则根据 注解中写明的组， 创建对应的 ServiceProxy
     * 然后使用ServiceProxy 为这个field生成代理类， 并注入
     *
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

        //寻找原始对象
        Object target = null;
        try {
            target = AopTargetUtils.getTarget(bean);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //获取target类的所有字段
        Field[] declaredFields = target.getClass().getDeclaredFields();
        for(Field field : declaredFields){
            RpcClient annotation = field.getAnnotation(RpcClient.class);
            if(annotation != null){
                //这个属性标注了这个注解
                String group = annotation.group();
                //TODO： 这里可以加一个ServiceProxyProvider 同一组的serviceProxy可以复用
                ServiceProxy serviceProxy = new ServiceProxy(Config.getRpcClient(), group);
                //为这个属性的类生成代理类
                Object proxy = serviceProxy.getProxy(field.getType());

                //赋值回去
                field.setAccessible(true);
                try {
                    //为原始对象target 的 field属性， 设置值，值为proxy
                    field.set(target,proxy);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
                logger.info("为{}类的{}注入{}组的代理类",bean.getClass().getCanonicalName(),field.getName(),group);
            }
        }
        return bean;
    }
}
